/**
 * User journey integration tests
 */

import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { QueryClient, QueryClientProvider } from 'react-query';
import { BrowserRouter } from 'react-router-dom';

// Mock localStorage
const localStorageMock = {
  getItem: jest.fn(),
  setItem: jest.fn(),
  removeItem: jest.fn(),
  clear: jest.fn(),
};
Object.defineProperty(window, 'localStorage', { value: localStorageMock });

// Mock API service
jest.mock('../../src/services/api', () => ({
  authApi: {
    login: jest.fn(),
    getCurrentUser: jest.fn(),
    validateToken: jest.fn(),
    refreshToken: jest.fn(),
  },
  telemetryApi: {
    getTelemetryPoints: jest.fn(),
    getTelemetryStats: jest.fn(),
  },
  teamApi: {
    getTeams: jest.fn(),
    createTeam: jest.fn(),
  },
}));

// Simple App component for testing
const MockApp: React.FC = () => {
  const [isAuthenticated, setIsAuthenticated] = React.useState(false);
  const [user, setUser] = React.useState(null);

  const handleLogin = async () => {
    // Mock login
    const mockUser = {
      user_id: 'test-user-123',
      email: 'test@example.com',
      name: 'Test User'
    };
    const mockToken = 'mock-token';

    localStorage.setItem('user', JSON.stringify(mockUser));
    localStorage.setItem('token', mockToken);

    setUser(mockUser);
    setIsAuthenticated(true);
  };

  const handleLogout = () => {
    localStorage.removeItem('user');
    localStorage.removeItem('token');
    setUser(null);
    setIsAuthenticated(false);
  };

  if (!isAuthenticated) {
    return (
      <div data-testid="login-page">
        <h1>登录</h1>
        <button onClick={handleLogin} data-testid="login-button">
          登录
        </button>
      </div>
    );
  }

  return (
    <div data-testid="dashboard">
      <h1>仪表板</h1>
      <p>欢迎, {user?.name}!</p>
      <button onClick={handleLogout} data-testid="logout-button">
        退出
      </button>
      <div data-testid="nav-menu">
        <button data-testid="nav-dashboard">仪表板</button>
        <button data-testid="nav-teams">团队管理</button>
        <button data-testid="nav-search">搜索</button>
      </div>
    </div>
  );
};

describe('User Journey Integration Tests', () => {
  let queryClient: QueryClient;

  beforeEach(() => {
    jest.clearAllMocks();
    queryClient = new QueryClient({
      defaultOptions: {
        queries: { retry: false },
        mutations: { retry: false },
      },
    });
  });

  afterEach(() => {
    localStorageMock.clear();
  });

  const renderWithProviders = (component: React.ReactElement) => {
    return render(
      <QueryClientProvider client={queryClient}>
        <BrowserRouter>
          {component}
        </BrowserRouter>
      </QueryClientProvider>
    );
  };

  describe('Login Flow', () => {
    test('user can view login page', () => {
      renderWithProviders(<MockApp />);

      expect(screen.getByTestId('login-page')).toBeInTheDocument();
      expect(screen.getByText('登录')).toBeInTheDocument();
      expect(screen.getByTestId('login-button')).toBeInTheDocument();
    });

    test('user can successfully login', async () => {
      renderWithProviders(<MockApp />);

      const loginButton = screen.getByTestId('login-button');
      fireEvent.click(loginButton);

      await waitFor(() => {
        expect(screen.getByTestId('dashboard')).toBeInTheDocument();
        expect(screen.getByText('欢迎, Test User!')).toBeInTheDocument();
      });

      expect(screen.getByTestId('logout-button')).toBeInTheDocument();
      expect(localStorageMock.setItem).toHaveBeenCalledWith('user', JSON.stringify({
        user_id: 'test-user-123',
        email: 'test@example.com',
        name: 'Test User'
      }));
      expect(localStorageMock.setItem).toHaveBeenCalledWith('token', 'mock-token');
    });

    test('user can logout successfully', async () => {
      renderWithProviders(<MockApp />);

      // First login
      const loginButton = screen.getByTestId('login-button');
      fireEvent.click(loginButton);

      await waitFor(() => {
        expect(screen.getByTestId('dashboard')).toBeInTheDocument();
      });

      // Then logout
      const logoutButton = screen.getByTestId('logout-button');
      fireEvent.click(logoutButton);

      await waitFor(() => {
        expect(screen.getByTestId('login-page')).toBeInTheDocument();
      });

      expect(localStorageMock.removeItem).toHaveBeenCalledWith('user');
      expect(localStorageMock.removeItem).toHaveBeenCalledWith('token');
    });
  });

  describe('Navigation Flow', () => {
    test('navigation menu is displayed after login', async () => {
      renderWithProviders(<MockApp />);

      // Login first
      const loginButton = screen.getByTestId('login-button');
      fireEvent.click(loginButton);

      await waitFor(() => {
        expect(screen.getByTestId('dashboard')).toBeInTheDocument();
        expect(screen.getByTestId('nav-menu')).toBeInTheDocument();
      });

      // Check navigation items
      expect(screen.getByTestId('nav-dashboard')).toBeInTheDocument();
      expect(screen.getByTestId('nav-teams')).toBeInTheDocument();
      expect(screen.getByTestId('nav-search')).toBeInTheDocument();
    });

    test('navigation items are clickable', async () => {
      renderWithProviders(<MockApp />);

      // Login first
      const loginButton = screen.getByTestId('login-button');
      fireEvent.click(loginButton);

      await waitFor(() => {
        expect(screen.getByTestId('dashboard')).toBeInTheDocument();
      });

      // Test navigation clicks
      const dashboardButton = screen.getByTestId('nav-dashboard');
      const teamsButton = screen.getByTestId('nav-teams');
      const searchButton = screen.getByTestId('nav-search');

      expect(dashboardButton).toBeEnabled();
      expect(teamsButton).toBeEnabled();
      expect(searchButton).toBeEnabled();

      // Click navigation items
      fireEvent.click(dashboardButton);
      fireEvent.click(teamsButton);
      fireEvent.click(searchButton);

      // In a real app, these would navigate to different pages
      // For now we just verify they can be clicked
      expect(dashboardButton).toBeInTheDocument();
      expect(teamsButton).toBeInTheDocument();
      expect(searchButton).toBeInTheDocument();
    });
  });

  describe('Persistence Flow', () => {
    test('user session persists after page reload', async () => {
      // Simulate stored user data
      const mockUser = {
        user_id: 'test-user-123',
        email: 'test@example.com',
        name: 'Test User'
      };
      localStorageMock.getItem.mockImplementation((key) => {
        if (key === 'user') return JSON.stringify(mockUser);
        if (key === 'token') return 'mock-token';
        return null;
      });

      // Clear and re-render to simulate page reload
      const { rerender } = renderWithProviders(<MockApp />);

      await waitFor(() => {
        expect(screen.getByTestId('dashboard')).toBeInTheDocument();
        expect(screen.getByText('欢迎, Test User!')).toBeInTheDocument();
      });

      expect(localStorageMock.getItem).toHaveBeenCalledWith('user');
    });

    test('handles missing stored data gracefully', () => {
      // Mock missing user data
      localStorageMock.getItem.mockReturnValue(null);

      renderWithProviders(<MockApp />);

      // Should show login page when no user data exists
      expect(screen.getByTestId('login-page')).toBeInTheDocument();
      expect(screen.getByText('登录')).toBeInTheDocument();
    });
  });

  describe('Error Handling Flow', () => {
    test('handles localStorage errors gracefully', async () => {
      // Mock localStorage to throw an error
      localStorageMock.setItem.mockImplementation(() => {
        throw new Error('Storage quota exceeded');
      });

      renderWithProviders(<MockApp />);

      const loginButton = screen.getByTestId('login-button');
      fireEvent.click(loginButton);

      // Should still render without crashing
      // In a real app, you might show an error message
      expect(screen.getByText('登录')).toBeInTheDocument();
    });
  });

  describe('Performance Flow', () => {
    test('renders components efficiently', async () => {
      const startTime = performance.now();

      renderWithProviders(<MockApp />);

      const loginButton = screen.getByTestId('login-button');
      fireEvent.click(loginButton);

      await waitFor(() => {
        expect(screen.getByTestId('dashboard')).toBeInTheDocument();
      });

      const endTime = performance.now();
      const renderTime = endTime - startTime;

      // Should render within reasonable time (e.g., 100ms)
      expect(renderTime).toBeLessThan(1000); // 1 second for safety
    });

    test('does not have memory leaks', () => {
      const { unmount } = renderWithProviders(<MockApp />);

      // Login and logout multiple times
      const loginButton = screen.getByTestId('login-button');

      for (let i = 0; i < 5; i++) {
        fireEvent.click(loginButton);

        waitFor(() => {
          if (screen.queryByTestId('dashboard')) {
            const logoutButton = screen.getByTestId('logout-button');
            fireEvent.click(logoutButton);
          }
        });
      }

      // Cleanup
      unmount();

      // Should not throw any errors during cleanup
      expect(true).toBe(true);
    });
  });
});